/*===========================================================================
  Copyright (C) 2014 by the Okapi Framework contributors
-----------------------------------------------------------------------------
  This library is free software; you can redistribute it and/or modify it 
  under the terms of the GNU Lesser General Public License as published by 
  the Free Software Foundation; either version 2.1 of the License, or (at 
  your option) any later version.

  This library is distributed in the hope that it will be useful, but 
  WITHOUT ANY WARRANTY; without even the implied warranty of 
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 
  General Public License for more details.

  You should have received a copy of the GNU Lesser General Public License 
  along with this library; if not, write to the Free Software Foundation, 
  Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

  See also the full LGPL text here: http://www.gnu.org/copyleft/lesser.html
===========================================================================*/

package net.sf.okapi.applications.lynxweb;

import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.regex.Pattern;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sf.okapi.lib.xliff2.URIParser;
import net.sf.okapi.lib.xliff2.Util;
import net.sf.okapi.lib.xliff2.document.XLIFFDocument;
import net.sf.okapi.lib.xliff2.reader.XLIFFReader;

@SuppressWarnings("serial")
public class FragmentIdentification extends HttpServlet
{
	static private String HEAD = Html.HEAD1+"XLIFF 2 Fragment Identification"+Html.HEAD2;

	static private String FORMPART1 = "<form action='/fragments' accept-charset='UTF-8' method='POST'>"
       	+ "<input style='font-weight:bold;padding:.5em' type='submit' value='Find the Referenced Fragment in the Document' /><br />"
       	+ "Reference: <input type='text' name='fragment' maxlength='100' value=\"";
	
	static private String FORMPART2 = "\" size='100'><br />"
		+ "<textarea rows='22' cols='100' name='content' maxlength='"+Html.FILESIZEMAX+"'>";
	
	static private String FORMPART3 = "</textarea><br />"
		+ "Map of non-standard prefixes (one &lt;uri>&lt;space>&lt;prefix> per line):<br />"
		+ "<textarea rows='6' cols='100' name='prefixes' maxlength='1000'>";
	
	static private String FORMPART4 = "</textarea>"
       	+ "</form>";
		
	static private String DEFCODE = "<xliff xmlns='urn:oasis:names:tc:xliff:document:2.0' version='2.0' \n"
		+ " srcLang='en' trgLang='fr'>\n"
		+ " <file id='1'>\n"
		+ "  <notes>\n"
		+ "   <note id='n1'>note for file</note>\n"
		+ "  </notes>\n"
		+ "  <unit id='1'>\n"
		+ "   <my:elem xmlns:my='myNamespaceURI' id='x1'>data</my:elem>\n"
		+ "   <notes>\n"
		+ "    <note id='n1'>note for unit</note>\n"
		+ "   </notes>\n"
		+ "   <originalData>\n"
		+ "    <data id='d1'>&lt;B></data>\n"
		+ "    <data id='d2'>&lt;/B></data>\n"
		+ "    <data id='d3'>&lt;BR></data>\n"
		+ "   </originalData>\n"
		+ "   <segment id='s1'>\n"
		+ "    <source><pc id='1' dataRefStart='d1' dataRefEnd='d2'>Hello "
		+ "<mrk id='m1' type='term'>World</mrk>!</pc><ph id='2' dataRef='d3'/></source>\n"
		+ "    <target><pc id='1' dataRefStart='d1' dataRefEnd='d2'>Bonjour le "
		+ "<mrk id='m1' type='term'>Monde</mrk> !</pc><ph id='2' dataRef='d3'/></target>\n"
		+ "   </segment>\n"
		+ "  </unit>\n"
		+ " </file>\n"
		+ "</xliff>";
	
	static final private Pattern EOL_PATTERN = Pattern.compile("\n|\r");

	@Override
    public void doGet(HttpServletRequest req,
    	HttpServletResponse resp)
    	throws ServletException, IOException
    {
		resp.setCharacterEncoding("UTF-8");
		resp.setContentType("text/html;charset=UTF-8");
        resp.getWriter().println(HEAD);
        resp.getWriter().println(FORMPART1+"#f=1/u=1"+FORMPART2+Util.toXML(DEFCODE, false)+FORMPART3
        	+"myNamespaceURI xyz"+FORMPART4);
        resp.getWriter().println(Html.INFO);
    }

	@Override
    public void doPost (HttpServletRequest req,
    	HttpServletResponse resp)
    	throws ServletException, IOException
    {
		String content = req.getParameter("content");
		String fragment = req.getParameter("fragment");
		String prefixes = req.getParameter("prefixes");
		String result;
		try {
			URIParser up = new URIParser("");
			if ( !Util.isNoE(prefixes) ) {
				Map<String, String> map = parsePrefixes(prefixes);
				up.addPrefixes(map);
			}
			up.setURL(fragment, null, null, null);
			XLIFFDocument doc = new XLIFFDocument();
			doc.load(content, XLIFFReader.VALIDATION_MAXIMAL);
			Object obj = doc.fetchReference(up);
			if ( obj == null ) {
				result = "<p style='background-color:orange;color:white;padding:.5em'>Fragment not found.</p>";
			}
			else {
				result = "<p style='background-color:green;color:white;padding:.5em'>Fragment found. "
					+ "Object type = "+obj.getClass().getName()+"</p>";
			}
		}
		catch ( Throwable e ) {
			result = "<p style='background-color:red;color:white;padding:.5em'>ERROR DETECTED:</p><pre>"
				+Util.toXML(e.getLocalizedMessage(), false)+"</pre>";
		}
		
		resp.setCharacterEncoding("UTF-8");
		resp.setContentType("text/html;charset=UTF-8");
        resp.getWriter().println(HEAD);
        resp.getWriter().println(result);
        resp.getWriter().println(FORMPART1+fragment+FORMPART2+Util.toXML(content, false)+FORMPART3
        	+prefixes+FORMPART4);
        resp.getWriter().println(Html.INFO);
    }

	private String trim (String line) {
		line = EOL_PATTERN.matcher(line).replaceAll("");
		return line.trim();
	}
	
	private Map<String, String> parsePrefixes (String text) {
		Map<String, String> map = new LinkedHashMap<String, String>();
		String[] lines = text.split("\n|\r", -1);
		for ( String line : lines ) {
			line = trim(line);
			if ( line.isEmpty() ) continue;
			String[] parts = line.split(" ", -1);
			if ( parts.length == 2 ) {
				map.put(parts[0], parts[1]);
			}
			else {
				throw new RuntimeException("Invalid line in prefixes definition: '"+line+"'.");
			}
		}
		return map;
	}
}
